/**
 * FtpClientUtil.java
 * 版权所有(C) 2013
 * 创建者:cuiran 2013-11-29 下午2:22:57
 */
package com.ghyf.mplay.net.ftp;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.util.ArrayList;

import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;

import com.ghyf.mplay.engine.XmlParser;
import com.ghyf.mplay.engineImpl.XmlparserImpl;
import com.ghyf.mplay.net.common.RecvBase;
import com.ghyf.mplay.net.common.RecvFileCmd;
import com.ghyf.mplay.util.LogUtil;
import com.ghyf.mplay.util.ShellUtils;
import com.ghyf.mplay.util.ShellUtils.CommandResult;
import com.ghyf.mplay.value.ConstantValue;

import android.content.Context;
import android.os.Environment;
import android.os.Handler;


/**
 *  FTP客户端上传下载工具类
 * @author cuiran
 * @version 1.0.0
 */
public class FtpClientUtil {
		protected static final String TAG = "FtpClientUtil";
		
		public static final int HANDLER_FTP_UPLOAD = 110;				// 上传文件
		/*** Set default timeoutSecond ***/
		private static final int DefaultTimeoutSecond=10;
		 /*** A constant indicating an FTPFile is a file. ***/
	    public static final int FILE_TYPE = 0;
	    /*** A constant indicating an FTPFile is a directory. ***/
	    public static final int DIRECTORY_TYPE = 1;
	    /*** A constant indicating an FTPFile is a symbolic link. ***/
	    public static final int SYMBOLIC_LINK_TYPE = 2;
	    /*** A constant indicating an FTPFile is of unknown type. ***/
	    public static final int UNKNOWN_TYPE = 3;
	
	    /**枚举类UploadStatus代码**/
		public enum UploadStatus {
			Create_Directory_Fail,     // 远程服务器相应目录创建失败
			Create_Directory_Success,  // 远程服务器闯将目录成功
			Upload_New_File_Success,   // 上传新文件成功
			Upload_New_File_Failed,    // 上传新文件失败
			File_Exits,                // 文件已经存在
			Remote_Bigger_Local,       // 远程文件大于本地文件
			Upload_From_Break_Success, // 断点续传成功
			Upload_From_Break_Failed,  // 断点续传失败
			Delete_Remote_Faild;       // 删除远程文件失败
		}
		// 枚举类DownloadStatus代码
		public enum DownloadStatus {
			Remote_File_Noexist, // 远程文件不存在
			Local_Bigger_Remote, // 本地文件大于远程文件
			Download_From_Break_Success, // 断点下载文件成功
			Download_From_Break_Failed, // 断点下载文件失败
			Download_New_Success, // 全新下载文件成功
			Download_New_Failed; // 全新下载文件失败
		}

		public FTPClient ftpClient =null;
		@SuppressWarnings("unused")
		private Context context;
		@SuppressWarnings("unused")
		private Handler handler;
	
		private static FtpClientUtil instance=null;
		private XmlParser parser;
		
		
		public FtpClientUtil(){
			
		}
		
		public FtpClientUtil(Context context, Handler handler){
			this.context = context;
			this.handler = handler;
			ftpClient = new FTPClient();
			ftpClient.setDefaultTimeout(DefaultTimeoutSecond * 1000);
			ftpClient.setConnectTimeout(DefaultTimeoutSecond * 1000);
			ftpClient.setDataTimeout(DefaultTimeoutSecond * 1000);
			ftpClient.setRemoteVerificationEnabled(false);//错误异常Host attempting data connection 192.168.90.151 is not same as server 192.168.90.24
		}
		
		public static  FtpClientUtil getInstance(Context context, Handler handler){
			if(instance==null){
				instance=new FtpClientUtil(context,handler);
			}
			
			return instance;
		}
		
		/**
		 * 
	     * @连接到Ftp
	     * @param hostname
	     * @param port
	     * @param username
	     * @param password
	     * @return
	     * @throws IOException
		 */
		public boolean connect(String hostname, int port, String username, String password) throws IOException {
			parser=new XmlparserImpl();
			ftpClient.setControlEncoding(RecvBase.charset);//设置字符集，必须在connect之前设置
			ftpClient.connect(hostname, port);//地址和端口
			
//			int timeout = 100000;//100秒
			if (FTPReply.isPositiveCompletion(ftpClient.getReplyCode())) {//？？？
				if (ftpClient.login(username, password)) {
					LogUtil.i(TAG, "成功连接FTP");
					return true;
				}
			}
			disconnect();
			return false;
		}
	     /**
	      * 创建本地目录<br>
	      * 2013-12-10 下午4:37:07
	      * @param localPath
	      */
		 private void createLogDir(String localPath) {  
		        File file=null;
		        boolean mkOk;  
		        if (Environment.getExternalStorageState().equals(  
		                Environment.MEDIA_MOUNTED)) {  
		            file = new File(localPath);  
		            if (!file.isDirectory()) {  
		                mkOk = file.mkdirs();  
		                if (!mkOk) {  
		                    return;  
		                }  
		            }  
		        }  
		    }  
		 
		 boolean isStop=false;
		 public class GetSizeThread extends Thread{
			 public long remoteSize=1;
			 public String remotePath="";
			 public String localPath;
			 private GetSizeThread(String remotePath,String localPath) {
				super();
				this.remotePath = remotePath;
				this.localPath=localPath;
			}


				/* (non-Javadoc)
				 * @see java.lang.Thread#run()
				 */
				@Override
				public void run() {
					File file=new File(localPath);
					remoteSize=downloadRemote(remotePath);
					if(remoteSize<=0)return;
					while(!isStop){
						try {
							long localSize=GetFileSizeUtil.getInstance().getFileSize(file);
							int progress=(int)(localSize*100/remoteSize);
							
//							 Intent mIntent = new Intent(RecvBase.ACTION_CMD_SEND);
//							 Bundle bundle=new Bundle();
//							 bundle.putInt(ConstantValue.EXTRA_TYPE, progress);
//							 mIntent.putExtra(ConstantValue.EXTRA_BUNDLE, bundle);
//							 //发送广播
//							 context.sendBroadcast(mIntent);
							 RecvFileCmd.progress=progress;
							
							if(progress>=100){
								isStop=true;
								this.interrupt();
							}
							Thread.sleep(100);
						} catch (InterruptedException e) {
							
							e.printStackTrace();
						} catch (Exception e) {
							
							e.printStackTrace();
						}
					}
					super.run();
				}
				
			}
		 
		 /**
		  * 获取服务器上的文件大小
		  * 2014-9-29 下午3:20:50
		  * @param remotePath
		  * @return
		  *
		  */
		 public long downloadRemote(String remotePath){
			
				ftpClient.enterLocalActiveMode();// 设置主动模式
//				ftpClient.enterLocalPassiveMode();// 设置被动模式
				// 设置以二进制方式传输
				try {
					ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
					FTPFile[] files = ftpClient.listFiles(remotePath);
					int length=files.length;
					for(int i=0;i<length;i++){
						FTPFile ftpfile=files[i];
						String name=ftpfile.getName();
						int type=ftpfile.getType();
						
						if("".equals(name)||null==name){
							/**
							 * name为空就跳过
							 */
							continue;
						}
						if(name.startsWith(".")){
							/**
							 * name为空就跳过
							 */
							continue;
						}
						if(type==FILE_TYPE){
							/**
							 * 如果为文件直接下载
							 */
							remoteSize+=ftpfile.getSize();
							/**
							 * 如果是xml文件需要判断资源文件
							 */
							String newLocalPath=remotePath+name;
							if(newLocalPath.endsWith(".XML")||newLocalPath.endsWith(".xml")){
								ArrayList<String> fileList=parser.parseModuleCheck(newLocalPath);
								if(null!=fileList&&fileList.size()>0){
									for(int m=0;m<fileList.size();m++){
										String fileName=fileList.get(m);
										File file=new File(ConstantValue.ROOT_DIR+"media/"+fileName);
										if(!file.exists()){
											FTPFile[] filess0 = ftpClient.listFiles(remotePath+fileName);
											int lengths0=filess0.length;
											if (lengths0 != 1) {
												FTPFile[] filess = ftpClient.listFiles(ConstantValue.SERVER_MEDIA+"/"+fileName);
												//检查
												int lengths=filess.length;
												if (lengths == 1) {
													remoteSize+=filess[0].getSize();
												}
											}
										}else{
											remoteSize+=file.length();
										}
										
									}
								}
							}
							
						}else if(type==DIRECTORY_TYPE){
							
							/**
							 * 如果为文件夹 递归
							 */
							downloadRemote(remotePath+name+"/");
						}
						
					}
				} catch (IOException e) {
					LogUtil.e(TAG, "download IOException", e);
				}catch (Exception e) {
					
					LogUtil.e(TAG, "download Exception", e);
				}
			 return remoteSize;
		 }
		 /**
		  * 下载视频目录
		  * 2013-12-25 下午1:53:11
		  * @param remotePath
		  * @param localPath
		  * @return
		  * @throws IOException
		  *
		  */
		 public DownloadStatus downloadMedia(String remotePath, String localPath) throws IOException {
				DownloadStatus result=null;
				LogUtil.i(TAG,"downloadprocess remotePath="+remotePath+"   localPath="+localPath);
				ftpClient.enterLocalActiveMode();// 设置主动模式
//				ftpClient.enterLocalPassiveMode();// 设置被动模式
				// 设置以二进制方式传输
				ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
				try{
					createLogDir(localPath);
					
					new GetSizeThread(remotePath, localPath).start();
					
					// 检查远程文件是否存在
					FTPFile[] files = ftpClient.listFiles(new String(remotePath.getBytes(RecvBase.charset), RecvBase.charset));
					int length=files.length;
					for(int i=0;i<length;i++){
						FTPFile ftpfile=files[i];
						String name=ftpfile.getName();
						int type=ftpfile.getType();
						
						if("".equals(name)||null==name){
							/**
							 * name为空就跳过
							 */
							continue;
						}
						if(name.startsWith(".")){
							/**
							 * name为空就跳过
							 */
							continue;
						}
						LogUtil.i(TAG,"downloadprocess name="+name+"-"+ftpfile.getSize()+"-"+type);
						if(type==FILE_TYPE){
							/**
							 * 如果为文件直接下载
							 */
							download(remotePath+name, localPath+name);
							
						}else if(type==DIRECTORY_TYPE){
							
							/**
							 * 如果为文件夹 递归
							 */
							downloadprocess(remotePath+name+"/", localPath+name+"/");
						}
						
					}
				}catch(Exception e){
					LogUtil.e(TAG, "download error", e);
				}
				return result;
			}
		 long remoteSize=0;
		 long localSize=0;
		/**
		 * 
		 * 获取下载进度线程 
		 * @author cuiran
		 * @version 1.0.0
		 */
		 public class GetProgressThread extends Thread{
			 int temp=0;
			@Override
			public void run() {
				super.run();
				while(true){
					try {
						//localSize<=remoteSize&&
						if(localSize>0&&remoteSize>0){
							int progress=(int)(localSize*100/remoteSize);
							if(temp!=progress){
								temp=progress;
								LogUtil.i(TAG, "localSize("+localSize+")  remoteSize("+remoteSize+")  progress*************="+progress);
								
								if(progress>=100){
									RecvFileCmd.progress=100;
									localSize=0;
									remoteSize=0;
									progressThread=null;
									break;
								}else{
									RecvFileCmd.progress=progress;
								}
							}
						}
						Thread.sleep(100);
					} catch (InterruptedException e) {
						e.printStackTrace();
					} catch (Exception e) {
						
						e.printStackTrace();
					}
				}
			}
			 
		 }
		 
		 public class GetLocalThread extends Thread{
			 private String filePath="";
			 
				private GetLocalThread(String filePath) {
				super();
				this.filePath = filePath;
			}
				long tempFile=0;
				@Override
				public void run() {
					super.run();
					while(true){
						try {
							if(null!=filePath&&"".equals(filePath)){
								File file=new File(filePath);
								
								if(file.exists()){
								long temp=file.length();
									if(tempFile>=temp){
										break;
									}else{
										localSize+=(temp-tempFile);
										tempFile=temp;
									}
								}
							}
							Thread.sleep(1000);
						} catch (InterruptedException e) {
							e.printStackTrace();
						} catch (Exception e) {
							
							e.printStackTrace();
						}
					}
				}
				 
			 }
			 
		 /**
		  * 对下载的xml文件进行检测
		  * 2014-10-21 上午10:06:27
		  * @param remotePath
		  * @param localPath
		  * @param name
		  *
		  */
		 @SuppressWarnings("unused")
		private void downloadCheck_bak(String remotePath,String localPath,String name){
			 try{
					/**
					 * 如果是xml文件需要判断资源文件
					 */
					String newLocalPath=localPath+name;//下载完成后本地的文件名字
					if(newLocalPath.endsWith(".XML")||newLocalPath.endsWith(".xml")){
						ArrayList<String> fileList=parser.parseModuleCheck(newLocalPath);
						
						if(null!=fileList&&fileList.size()>0){
							/**
							 * 第一个for循环是为了获取ftp服务器上文件的大小
							 */
							for(int m=0;m<fileList.size();m++){
								String fileName=fileList.get(m);
									//??这里暂且没有考虑文件名带空格的情况，若文件名带空格这里是无法获取文件
									FTPFile[] filess = ftpClient.listFiles(remotePath+fileName);
									//检查同一目录是否存在资源文件 不等于1 说明文件不存在此目录 而是在media目录
									if (filess.length != 1) {
										String path=ConstantValue.SERVER_MEDIA+"/"+fileName;
										FTPFile[] filess1 =ftpClient.listFiles(path); 
										int lengths=filess1.length;
										if (lengths == 1) {
											remoteSize+=filess1[0].getSize();
											LogUtil.i(TAG, "path ("+path+") remoteSize("+remoteSize+") filess1[0].getSize()=("+filess1[0].getSize()+")");
										}
									}else{
										//同一目录存在资源文件，将此大小添加到remoteSize中
										remoteSize+=filess[0].getSize();
									}
									
							}
							/**
							 * 第二个for循环是为了下载所使用的媒体文件在ftp服务器中MEDIA目录下
							 */
							for(int m=0;m<fileList.size();m++){
								
								String fileName=fileList.get(m);
								String locatPath=ConstantValue.ROOT_DIR+"media/"+fileName;
								//先判断本地是否存在此文件
								File file=new File(locatPath);
								if(!file.exists()){
									FTPFile[] filess = ftpClient.listFiles(remotePath+fileName);
									//检查同一目录是否存在资源文件   不等于1： 说明文件不存在此目录 而是在MEDIA目录
									if (filess.length != 1) {
										/**
										 * 直接从MEDIA目录下载
										 */
										String localDown= ConstantValue.ROOT_DIR+"media/"+fileName;
										download(ConstantValue.SERVER_MEDIA+"/"+fileName, localDown);
										//下载完成后，执行文件的权限为777
										CommandResult cr = ShellUtils.execCommand("busybox chmod -f 777 " + ConstantValue.ROOT_DIR+"media/"+fileName ,ShellUtils.checkRootPermission()) ;
										LogUtil.i(TAG, "chmodeth：successMsg="+cr.successMsg+"-result="+cr.result+"-errorMsg="+cr.errorMsg);
									}
								}else{
									long tempSize=file.length();//先获取文件大小
									FTPFile[] filess1 =ftpClient.listFiles(ConstantValue.SERVER_MEDIA+"/"+fileName); 
									if(tempSize<filess1[0].getSize()){
										//上一次没有下载完，断点续传
										/**
										 * 如果文件直接下载
										 */
										String localDown= ConstantValue.ROOT_DIR+"media/"+fileName;
										download(ConstantValue.SERVER_MEDIA+"/"+fileName, localDown);
										//下载完成后，执行文件的权限为777
										CommandResult cr = ShellUtils.execCommand("busybox chmod -f 777 " + ConstantValue.ROOT_DIR+"media/"+fileName ,ShellUtils.checkRootPermission()) ;
										LogUtil.i(TAG, "chmodeth：successMsg="+cr.successMsg+"-result="+cr.result+"-errorMsg="+cr.errorMsg);
									}else{
										localSize+=tempSize;
										LogUtil.i(TAG, "locatPath ("+locatPath+") localSize("+localSize+" tempSize("+tempSize+") " );
									}
									
								}
								
							}
						}
					}
					
			 }catch(Exception e){
				 LogUtil.e(TAG, "downloadprocess found error", e);
			 }
		 }
		 
		 /**
		  * 对下载的xml文件进行检测  如果是xml文件需要判断资源文件
		  * 2014-10-21 上午10:06:27
		  * @param remotePath
		  * @param localPath
		  * @param name
		  *
		  */
		 private void downloadCheck(String remotePath,String localPath,String name){
			 try{
					String newLocalPath=localPath+name;//下载完成后本地的文件名字
					if(newLocalPath.endsWith(".XML")||newLocalPath.endsWith(".xml")){
						ArrayList<String> fileList=parser.parseModuleCheck(newLocalPath);
						if(null!=fileList&&fileList.size()>0){
							/**
							 * 第一个for循环是为了获取ftp服务器上文件的大小
							 */
							for(int m=0;m<fileList.size();m++){
								String fileName=fileList.get(m);
									//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
								    //这里暂且没有考虑文件名带空格的情况，若文件名带空格这里是无法获取文件
								    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
									FTPFile[] filess = ftpClient.listFiles(remotePath+fileName);
									//检查同一目录是否存在资源文件 不等于1 说明文件不存在此目录 而是在media目录
									if (filess.length != 1) {
										String path=ConstantValue.SERVER_MEDIA+"/"+fileName;
										FTPFile[] filess1 =ftpClient.listFiles(path); 
										int lengths=filess1.length;
										if (lengths == 1) {
											remoteSize+=filess1[0].getSize();
											LogUtil.i(TAG, "path ("+path+") remoteSize("+remoteSize+") filess1[0].getSize()=("+filess1[0].getSize()+")");
										}
									}else{
										//同一目录存在资源文件，将此大小添加到remoteSize中
										remoteSize+=filess[0].getSize();
									}
									
							}
							/**
							 * 第二个for循环是为了下载所使用的媒体文件在ftp服务器中MEDIA目录下
							 */
							for(int m=0;m<fileList.size();m++){
								String fileName=fileList.get(m);
								FTPFile[] filess = ftpClient.listFiles(remotePath+fileName);
									//检查同一目录是否存在资源文件   不等于1： 说明文件不存在此目录 而是在MEDIA目录
									if (filess.length != 1) {
										/**
										 * 直接从MEDIA目录下载
										 */
										String localDown= ConstantValue.ROOT_DIR+"media/"+fileName;
										download(ConstantValue.SERVER_MEDIA+"/"+fileName, localDown);
										//下载完成后，执行文件的权限为777
										CommandResult cr = ShellUtils.execCommand("busybox chmod -f 777 " + ConstantValue.ROOT_DIR+"media/"+fileName ,ShellUtils.checkRootPermission()) ;
										LogUtil.i(TAG, "chmodeth：successMsg="+cr.successMsg+"-result="+cr.result+"-errorMsg="+cr.errorMsg);
									}
							}
						}
					}
					
			 }catch(Exception e){
				 LogUtil.e(TAG, "downloadprocess found error", e);
			 }
		 }
		 private GetProgressThread progressThread=null;
		/**
		 * 从Ftp服务器下载文件夹
		 * 2013-12-10 下午3:28:27
		 * @param remotePath 远程文件夹路径
		 * @param localPath 本地文件夹路径
		 * @return
		 * @throws IOException
		 *
		 */
		public DownloadStatus downloadprocess(String remotePath, String localPath) throws IOException {
			DownloadStatus result=null;
			LogUtil.i(TAG,"downloadprocess remotePath="+remotePath+"   localPath="+localPath);
			ftpClient.enterLocalActiveMode();// 设置主动模式
//			ftpClient.enterLocalPassiveMode();// 设置被动模式
			// 设置以二进制方式传输
			ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
			try{
				createLogDir(localPath);
				if(null==progressThread){
					progressThread=new GetProgressThread();
					progressThread.start();
				}
				// 检查远程文件是否存在
				FTPFile[] files = ftpClient.listFiles(remotePath);
				int length=files.length;
				for(int i=0;i<length;i++){
					FTPFile ftpfile=files[i];
					String name=ftpfile.getName();
					int type=ftpfile.getType();
					if("".equals(name)||null==name){
						continue;// name为空就跳过
					}
					if(name.startsWith(".")){
						continue;// name为空就跳过
					}
					if(type==FILE_TYPE){
						//如果为文件直接下载
						result=download(remotePath+name, localPath+name);
						//对下载的xml文件进行检测
						downloadCheck(remotePath, localPath, name);
						
					}else if(type==DIRECTORY_TYPE){
						//如果为文件夹 递归
						downloadprocess(remotePath+name+"/", localPath+name+"/");
					}
					
				}
			}catch(Exception e){
				result=DownloadStatus.Download_New_Failed;
				progressThread=null;
				/**
				 * 捕获异常后 需要重新下载此播表
				 */
				LogUtil.e(TAG, "downloadprocess found error", e);
			}
			return result;
		}
	
		OutputStream out=null;
		InputStream in=null;
		/**
		 * 
	     * @下载文件
	     * @param remote
	     * @param local
	     * @return
	     * @throws IOException
		 */
		public DownloadStatus download2(String remote, String local) throws IOException {
			ftpClient.enterLocalActiveMode();// 设置主动模式
//			ftpClient.enterLocalPassiveMode();// 设置被动模式
			// 设置以二进制方式传输
			ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
			DownloadStatus result=null;
			try{
				// 检查远程文件是否存在
				FTPFile[] files = ftpClient.listFiles(new String(remote.getBytes("utf-8"), "utf-8"));
				if (files.length != 1) {
					LogUtil.i(TAG,"远程文件不存在 remote("+remote+")");
					return DownloadStatus.Remote_File_Noexist;
				}
				File f = new File(local);
					
				// 本地存在文件，进行断点下载
				if (true) {
					 out = new FileOutputStream(f);
//					 in = ftpClient.retrieveFileStream(new String(remote.getBytes("utf-8"), "utf-8"));
					 ftpClient.retrieveFile(new String(remote.getBytes("utf-8"), "utf-8"), out);
					 out.close();
					 in = new FileInputStream(f);
					
					 boolean upNewStatus = ftpClient.completePendingCommand();
					 if (upNewStatus) {
							result = DownloadStatus.Download_New_Success;
					} else{
							result = DownloadStatus.Download_New_Failed;
					}
//					byte[] bytes = new byte[1024];
//					int c;
//					while ((c = in.read(bytes)) != -1) {
//						out.write(bytes, 0, c);
//					}
					
				}
			}catch(Exception e){
				LogUtil.e(TAG, "download error", e);
			}finally{
				
			}
			
			
			return result;
		}
		
		/**
		 * 下载文件
		 * 2014-10-21 上午10:20:29
		 * @param remote 远程ftp地址
		 * @param local  本地地址
		 * @return
		 * @throws IOException
		 *
		 */
		public DownloadStatus download(String remote, String local) throws IOException {
			ftpClient.enterLocalActiveMode();// 设置主动模式
//			ftpClient.enterLocalPassiveMode();// 设置被动模式
			// 设置以二进制方式传输
			ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
			DownloadStatus result=null;
			boolean isAdd=false;
			try{
				LogUtil.i(TAG,"检查远程文件是否存在 remote("+remote+")  local("+local+")");
				if(local.endsWith(".mpg")
						||local.endsWith(".mkv")
						||local.endsWith(".mp4")
						||local.endsWith(".flv")
						||local.endsWith(".avi")
						||local.endsWith(".MPG")
						||local.endsWith(".MKV")
						||local.endsWith(".MP4")
						||local.endsWith(".FLV")
						||local.endsWith(".AVI")){
					isAdd=true;
				}
				// 检查远程文件是否存在 但是对于有空格的文件名字不能使用
				FTPFile[] files = ftpClient.listFiles(remote);
				if (files.length != 1) {
					LogUtil.i(TAG,"远程文件不存在 remote("+remote+")");
				}
				long lRemoteSize = files[0].getSize();
				
				File f = new File(local);
				//判断如果是视频大文件 采取断点续传
				if(isAdd){
					if(f.exists()){
						//本地存在视频文件 断点续传
						long localSize1 = f.length();
						localSize+=localSize1;
						if (localSize1 >= lRemoteSize) {
							LogUtil.i(TAG,"本地文件大于等于远程文件，下载中止");
							
							return DownloadStatus.Local_Bigger_Remote;
						}
						//设置下载的位置
						out = new FileOutputStream(f,true);//追加模式添加到存在的文件中
						ftpClient.setRestartOffset(localSize1);
						
					}else{
						out = new FileOutputStream(f);
					}
					in = ftpClient.retrieveFileStream(remote);
					if(in==null) {
						LogUtil.i(TAG,"远程文件不存在 remote("+remote+")");
						return DownloadStatus.Remote_File_Noexist;
					}
					byte[] bytes = new byte[1024];
					int c;
					while ((c = in.read(bytes)) != -1) {
						localSize+=c;
						out.write(bytes, 0, c);
					}
				}else{
					f.createNewFile();
					out = new FileOutputStream(f);
					in = ftpClient.retrieveFileStream(remote);
					if(in==null) {
						LogUtil.i(TAG,"远程文件不存在 remote("+remote+")");
						return DownloadStatus.Remote_File_Noexist;
					}
					byte[] bytes = new byte[1024];
					int c;
					while ((c = in.read(bytes)) != -1) {
						out.write(bytes, 0, c);
					}
				}
				
					if(in!=null){
						in.close();
					}
					if(out!=null){
						out.close();
					}
					boolean upNewStatus = ftpClient.completePendingCommand();
					if (upNewStatus) {
						result = DownloadStatus.Download_New_Success;
					} else {
						result = DownloadStatus.Download_New_Failed;
					}
				
			}catch(Exception e){
				result = DownloadStatus.Download_New_Failed;
				LogUtil.e(TAG, "download error", e);
			}
			return result;
		}
		
		/**
		 * 下载文件
		 * 2014-10-21 上午10:20:29
		 * @param remote 远程ftp地址
		 * @param local  本地地址
		 * @return
		 * @throws IOException
		 *
		 */
		public DownloadStatus download1021(String remote, String local) throws IOException {
			ftpClient.enterLocalActiveMode();// 设置主动模式
//			ftpClient.enterLocalPassiveMode();// 设置被动模式
			// 设置以二进制方式传输
			ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
			DownloadStatus result=null;
			boolean isAdd=false;
			try{
				LogUtil.i(TAG,"检查远程文件是否存在 remote("+remote+")  local("+local+")");
				if(local.endsWith(".mpg")
						||local.endsWith(".mkv")
						||local.endsWith(".mp4")
						||local.endsWith(".flv")
						||local.endsWith(".avi")){
					isAdd=true;
				}
				// 检查远程文件是否存在 但是对于有空格的文件名字不能使用
				FTPFile[] files = ftpClient.listFiles(remote);
				if (files.length != 1) {
					LogUtil.i(TAG,"远程文件不存在 remote("+remote+")");
				}
				long lRemoteSize = files[0].getSize();
				File f = new File(local);
				if(isAdd){
					if(f.exists()){
						//本地存在视频文件 断点续传
						long localSize1 = f.length();
						if (localSize1 >= lRemoteSize) {
							LogUtil.i(TAG,"本地文件大于等于远程文件，下载中止");
							return DownloadStatus.Local_Bigger_Remote;
						}
						out = new FileOutputStream(f,true);
						ftpClient.setRestartOffset(localSize1);
						in = ftpClient.retrieveFileStream(remote);
					
						if(in==null) return DownloadStatus.Remote_File_Noexist;
						byte[] bytes = new byte[1024];
						int c;
						while ((c = in.read(bytes)) != -1) {
							localSize+=c;
							out.write(bytes, 0, c);
						}
					}else{
						out = new FileOutputStream(f,true);
						in = ftpClient.retrieveFileStream(remote);
						if(in==null) return DownloadStatus.Remote_File_Noexist;
						byte[] bytes = new byte[1024];
						int c;
						while ((c = in.read(bytes)) != -1) {
							localSize+=c;
							out.write(bytes, 0, c);
						}
					}
				
				}else{
					f.createNewFile();
					out = new FileOutputStream(f);
					in = ftpClient.retrieveFileStream(remote);
					if(in==null) return DownloadStatus.Remote_File_Noexist;
					byte[] bytes = new byte[1024];
					int c;
					while ((c = in.read(bytes)) != -1) {
						out.write(bytes, 0, c);
					}
				}
				
			}catch(Exception e){
				LogUtil.e(TAG, "download error", e);
			}finally{
				if(in!=null){
					in.close();
				}
				if(out!=null){
					out.close();
				}
				boolean upNewStatus = ftpClient.completePendingCommand();
				if (upNewStatus) {
					result = DownloadStatus.Download_New_Success;
				} else {
					result = DownloadStatus.Download_New_Failed;
				}
			}
			return result;
		}
		public DownloadStatus download1017(String remote, String local) throws IOException {
			ftpClient.enterLocalActiveMode();// 设置主动模式
//			ftpClient.enterLocalPassiveMode();// 设置被动模式
			// 设置以二进制方式传输
			ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
			DownloadStatus result=null;
			boolean isAdd=false;
			try{
				LogUtil.i(TAG,"检查远程文件是否存在 remote("+remote+")  local("+local+")");
				if(local.endsWith(".mpg")
						||local.endsWith(".mkv")
						||local.endsWith(".mp4")
						||local.endsWith(".flv")
						||local.endsWith(".avi")){
					isAdd=true;
				}
				// 检查远程文件是否存在 但是对于有空格的文件名字不能使用
				FTPFile[] files = ftpClient.listFiles(remote);
				if (files.length != 1) {
					LogUtil.i(TAG,"远程文件不存在 remote("+remote+")");
//					return DownloadStatus.Remote_File_Noexist;
				}
				File f = new File(local);
				f.createNewFile();
				out = new FileOutputStream(f);
				in = ftpClient.retrieveFileStream(remote);
			
				if(in==null) return DownloadStatus.Remote_File_Noexist;
				byte[] bytes = new byte[1024];
				int c;
				if(isAdd){
					while ((c = in.read(bytes)) != -1) {
						localSize+=c;
						out.write(bytes, 0, c);
//						LogUtil.i(TAG,"localSize("+localSize+")");
					}
				}else{
					while ((c = in.read(bytes)) != -1) {
						out.write(bytes, 0, c);
//						LogUtil.i(TAG,"11localSize("+localSize+")");
					}
				}
				
			}catch(Exception e){
				LogUtil.e(TAG, "download error", e);
			}finally{
				if(in!=null){
					in.close();
				}
				if(out!=null){
					out.close();
				}
				boolean upNewStatus = ftpClient.completePendingCommand();
				if (upNewStatus) {
					result = DownloadStatus.Download_New_Success;
				} else {
					result = DownloadStatus.Download_New_Failed;
				}
			}
			return result;
		}
		
		public DownloadStatus download1(String remote, String local) throws IOException {
			
			ftpClient.enterLocalActiveMode();// 设置主动模式
//			ftpClient.enterLocalPassiveMode();// 设置被动模式
			// 设置以二进制方式传输
			ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
			DownloadStatus result=null;

			try{
				// 检查远程文件是否存在
				FTPFile[] files = ftpClient.listFiles(new String(remote.getBytes("utf-8"), "utf-8"));
				if (files.length != 1) {
					LogUtil.i(TAG,"远程文件不存在");
					return DownloadStatus.Remote_File_Noexist;
				}

				long lRemoteSize = files[0].getSize();
				File f = new File(local);
				// 本地存在文件，进行断点下载
				if (f.exists()) {
					long localSize = f.length();
					// 判断本地文件大小是否大于远程文件大小
					if (localSize >= lRemoteSize) {
						LogUtil.i(TAG,"本地文件大于或等于远程文件，下载中止");
						return DownloadStatus.Local_Bigger_Remote;
					}

					// 进行断点续传，并记录状态
					FileOutputStream out = new FileOutputStream(f, true);
					ftpClient.setRestartOffset(localSize);
					InputStream in = ftpClient.retrieveFileStream(new String(remote.getBytes("utf-8"), "utf-8"));
					byte[] bytes = new byte[1024];
//					long step = lRemoteSize / 100;
//					long process = localSize / step;
					int c;
					while ((c = in.read(bytes)) != -1) {//断开连接后不到10秒，报错
						out.write(bytes, 0, c);
						localSize += c;
//						long nowProcess = localSize / step;
//						if (nowProcess > process) {
//							process = nowProcess;
//							if (process % 10 == 0)
//								System.out.println("下载进度：" + process);
//							// 更新文件下载进度,值存放在process变量中
//						}
					}
					in.close();
					out.close();
					boolean isDo = ftpClient.completePendingCommand();
					if (isDo) {
						result = DownloadStatus.Download_From_Break_Success;
					} else {
						result = DownloadStatus.Download_From_Break_Failed;
					}
				} else {
					OutputStream out = new FileOutputStream(f);
					InputStream in = ftpClient.retrieveFileStream(new String(remote.getBytes("utf-8"), "utf-8"));
					byte[] bytes = new byte[1024];
//					long step = lRemoteSize / 100;
//					long process = 0;
//					long localSize = 0L;
					int c;
					while ((c = in.read(bytes)) != -1) {
						out.write(bytes, 0, c);
//						localSize += c;
//						long nowProcess = localSize / step;
//						if (nowProcess > process) {
//							process = nowProcess;
//							if (process % 10 == 0)
//								System.out.println("下载进度：" + process);
//							//  更新文件下载进度,值存放在process变量中
//						}
					}
					in.close();
					out.close();
					boolean upNewStatus = ftpClient.completePendingCommand();
					if (upNewStatus) {
						result = DownloadStatus.Download_New_Success;
					} else {
						result = DownloadStatus.Download_New_Failed;
					}
				}
			}catch(Exception e){
				LogUtil.e(TAG, "download error", e);
			}
			
			
			return result;
		}
		/**
		 * 上传文件 从本机文件夹上传到FTP服务器文件夹<br>
		 * 2013-12-10 下午4:59:11
		 * @param localPath 本机文件夹
		 * @param remotePath 远程文件夹
		 * @return
		 * @throws IOException
		 *
		 */
		public UploadStatus uploadprocess(String localPath, String remotePath) throws IOException {
//			LogUtil.i(TAG, "local="+localPath+" remote="+remotePath);
			ftpClient.enterLocalPassiveMode();// 设置PassiveMode传输
//			ftpClient.enterLocalActiveMode();// 设置ActiveMode传输
			ftpClient.setBufferSize(1024);
			ftpClient.setControlEncoding("UTF-8");
			// 设置以二进制流的方式传输
			ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
			UploadStatus result=null;
			
			try{
				File file0=new File(localPath);
				File[] files=file0.listFiles();
				int length=files.length;
//				LogUtil.i(TAG,"uploadprocess size="+length);
				for(int i=0;i<length;i++){
					File file=files[i];
					String name=file.getName();
//					LogUtil.i(TAG,"uploadprocess name="+name);
					if(file.isDirectory()){
						/**
						 * 如果是文件夹 递归
						 */
						uploadprocess(localPath+"/"+name, remotePath+"/"+name);
						
					}
					if(file.isFile()){
						
						
						ftpClient.changeWorkingDirectory("/");
						
						upload(localPath+"/"+name, remotePath+"/"+name);
						
						
					}
				}
				
			}catch(Exception e){
				LogUtil.e(TAG, "upload error", e);
			}
			
			return result;
		}

		/**
		 * 
	     * @上传文件
	     * @param local
	     * @param remote
	     * @return
	     * @throws IOException
		 */
		public UploadStatus upload(String local, String remote) throws IOException {
			LogUtil.i(TAG, "local="+local+" remote="+remote);
			ftpClient.enterLocalPassiveMode();// 设置PassiveMode传输
//			ftpClient.enterLocalActiveMode();// 设置ActiveMode传输
			ftpClient.setBufferSize(1024);
			ftpClient.setControlEncoding("UTF-8");
			// 设置以二进制流的方式传输
			ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
			UploadStatus result=null;
			try{
				// 对远程目录的处理
				String remoteFileName = remote;
				if (remote.contains("/")) {
					remoteFileName = remote.substring(remote.lastIndexOf("/") + 1);
					// 创建服务器远程目录结构，创建失败直接返回
					if (CreateDirecroty(remote, ftpClient) == UploadStatus.Create_Directory_Fail) {
						return UploadStatus.Create_Directory_Fail;
					}
				}
				
//				LogUtil.i(TAG, "路径："+new String(remoteFileName.getBytes("utf-8"), "utf-8"));
				// 检查远程是否存在文件
				FTPFile[] files = ftpClient.listFiles(new String(remoteFileName.getBytes("utf-8"), "utf-8"));
//				LogUtil.i(TAG, "files length："+files.length);
				if (files.length == 1) {
					long remoteSize = files[0].getSize();
					File f = new File(local);
					LogUtil.i(TAG,f.getName());
					long localSize = f.length();
					if (remoteSize == localSize) {
//						LogUtil.i(TAG,"服务器中文件等于要上传文件，所以不上传");
						return UploadStatus.File_Exits;
					} else if (remoteSize > localSize) {
//						LogUtil.i(TAG,"服务器中文件大于要上传文件，所以不上传");
						return UploadStatus.Remote_Bigger_Local;
					}
//					LogUtil.i(TAG,"localSize="+localSize+" remoteSize="+remoteSize);
					// 尝试移动文件内读取指针,实现断点续传
					result = uploadFile(remoteFileName, f, ftpClient, remoteSize);

					// 如果断点续传没有成功，则删除服务器上文件，重新上传
					if (result == UploadStatus.Upload_From_Break_Failed) {
						if (!ftpClient.deleteFile(remoteFileName)) {
							return UploadStatus.Delete_Remote_Faild;
						}
						result = uploadFile(remoteFileName, f, ftpClient, 0);
					}
				} else {
					result = uploadFile(remoteFileName, new File(local), ftpClient, 0);
				}
			}catch(Exception e){
				LogUtil.e(TAG, "upload error", e);
			}
			
			
			return result;
		}

		/**
		 * 断开与远程服务器的连接
		 * 
		 * @throws IOException
		 */
		public void disconnect() throws IOException {
			if (ftpClient.isConnected()) {
				ftpClient.disconnect();
			}
		}

		/**
		 * 递归创建远程服务器目录
		 * 
		 * @param remote
		 *            远程服务器文件绝对路径
		 * @param ftpClient
		 *            FTPClient 对象
		 * @return 目录创建是否成功
		 * @throws IOException
		 */
		public UploadStatus CreateDirecroty(String remote, FTPClient ftpClient) throws IOException {
			UploadStatus status = UploadStatus.Create_Directory_Success;
			String directory = remote.substring(0, remote.lastIndexOf("/") + 1);
//			LogUtil.i(TAG,"目录名："+new String(directory.getBytes("utf-8"), "utf-8"));
			if (!directory.equalsIgnoreCase("/")
					&& !ftpClient.changeWorkingDirectory(new String(directory.getBytes("utf-8"), "utf-8"))) {
				// 如果远程目录不存在，则递归创建远程服务器目录
				int start = 0;
				int end = 0;
				if (directory.startsWith("/")) {
					start = 1;
				} else {
					start = 0;
				}
				end = directory.indexOf("/", start);
				while (true) {
					String subDirectory = new String(remote.substring(start, end).getBytes("utf-8"), "utf-8");
//					LogUtil.i(TAG,"subDirectory = "+subDirectory);
					if (!ftpClient.changeWorkingDirectory(subDirectory)) {
						if (ftpClient.makeDirectory(subDirectory)) {
							ftpClient.changeWorkingDirectory(subDirectory);
							LogUtil.i(TAG,"创建目录成功");
						} else {
							LogUtil.i(TAG,"创建目录失败,或已存在");
							return UploadStatus.Create_Directory_Fail;
						}
					}

					start = end + 1;
					end = directory.indexOf("/", start);

					// 检查所有目录是否创建完毕
					if (end <= start) {
						break;
					}
				}
			}
			return status;
		}

		/**
		 * 上传文件到服务器,新上传和断点续传
		 * 
		 * @param remoteFile
		 *            远程文件名，在上传之前已经将服务器工作目录做了改变
		 * @param localFile
		 *            本地文件 File句柄，绝对路径
		 * @param processStep
		 *            需要显示的处理进度步进值
		 * @param ftpClient
		 *            FTPClient 引用
		 * @return
		 * @throws IOException
		 */
		@SuppressWarnings("unused")
		public UploadStatus uploadFile(String remoteFile, File localFile, FTPClient ftpClient, long remoteSize)
				throws IOException {
			UploadStatus status=null;
			try{
				// 显示进度的上传
				long step = localFile.length() / 100;
				long process = 0;
				long localreadbytes = 0L;
				RandomAccessFile raf = new RandomAccessFile(localFile, "r");
				OutputStream out = ftpClient.appendFileStream(new String(remoteFile.getBytes("utf-8"), "utf-8"));
				// 断点续传
				if (remoteSize > 0) {
					ftpClient.setRestartOffset(remoteSize);
//					process = remoteSize / step;
					raf.seek(remoteSize);
					localreadbytes = remoteSize;
				}
				byte[] bytes = new byte[1024];
				int c;
				while ((c = raf.read(bytes)) != -1) {
					out.write(bytes, 0, c);
					localreadbytes += c;
//					if (localreadbytes / step != process) {
//						process = localreadbytes / step;
//						System.out.println("上传进度:" + process);
//						Message msg = handler.obtainMessage();
//						msg.arg1 = (int) process;
//						handler.sendMessage(msg);
//						LogUtil.i("上传进度:", process + "");
//					}
				}
				out.flush();
				raf.close();
				out.close();
				boolean result = ftpClient.completePendingCommand();
				if (remoteSize > 0) {
					status = result ? UploadStatus.Upload_From_Break_Success : UploadStatus.Upload_From_Break_Failed;
				} else {
					status = result ? UploadStatus.Upload_New_File_Success : UploadStatus.Upload_New_File_Failed;
				}
			}catch(Exception e){
				LogUtil.e(TAG, "uploadFile", e);
			}
			
			return status;
		}

 		/**
		 * 通过ftp上传文件
		 * @param url ftp服务器地址 如： 192.168.1.110
		 * @param port 端口如 ： 21
		 * @param username  登录名
		 * @param password   密码
		 * @param remotePath  上传到ftp服务器的磁盘路径
		 * @param fileNamePath  要上传的文件路径
		 * @param fileName		要上传的文件名
		 * @return
		 */
	 public String ftpUpload(String url, String port, String username,String password, String remotePath, String fileNamePath,String fileName) {
		 FTPClient ftpClient = new FTPClient();
		 FileInputStream fis = null;
		 String returnMessage = "0";
		 try {
			 ftpClient.connect(url, Integer.parseInt(port));
			 boolean loginResult = ftpClient.login(username, password);
			 int returnCode = ftpClient.getReplyCode();
			 if (loginResult && FTPReply.isPositiveCompletion(returnCode)) {// 如果登录成功
				 ftpClient.makeDirectory(remotePath);
				 // 设置上传目录
				 ftpClient.changeWorkingDirectory(remotePath);
				 ftpClient.setBufferSize(1024);
				 ftpClient.setControlEncoding("UTF-8");
				 ftpClient.enterLocalPassiveMode();
						 fis = new FileInputStream(fileNamePath + fileName);
				 ftpClient.storeFile(fileName, fis);
				 
				 returnMessage = "0";   //上传成功 	
				 
			 } else {// 如果登录失败
				
				 returnMessage = "1";
				
			 }
			 		 
		 } catch (IOException e) {
			 throw new RuntimeException("FTP客户端出错！", e);
		 } finally {
			 //IOUtils.closeQuietly(fis);
			 try {
				 ftpClient.disconnect();
		 		} catch (IOException e) {
			 	
			 	throw new RuntimeException("关闭FTP连接发生异常！", e);
		 		}
		 }
		 return returnMessage;
	 }

}
